package com.mobileClientKernel.android.serviceManager.network;

import com.mobileClientKernel.android.serviceManager.network.requestexecutor.VolleyExecutor;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by hamilyjing on 4/9/16.
 */
public class JJNetworkAgent {

    public static final String RESPCODE = "responseCode";
    public static final String RESPCONTENT = "responseContent";
    public static final String RESPERROR = "errorContent";
    public static final String RESPHEADERS = "responseHeaders";
    public static final String REQINDEX = "requestIndex";

    private IRequest client;

    private HashMap<Integer, JJBaseRequest> requestHashMap = new HashMap<>();
    private Integer requestIndex = 1;

    private Lock lock = new ReentrantLock(); // 定义锁对象

    private static JJNetworkAgent instance = new JJNetworkAgent(new VolleyExecutor());

    public static JJNetworkAgent getInstance() {
        return instance;
    }

    private JJNetworkAgent(IRequest request) {
        this.client = request;
    }

    public void addRequest(JJBaseRequest request) {
        final Integer index = addOperation(request);
        client.executeRequest(request, index, new IRequest.ResponseListener() {
            @Override
            public void onSuccess(Map<String, Object> responseMap) {
                JJNetworkAgent.this.onSuccess(responseMap);
            }

            @Override
            public void onFailure(Map<String, Object> responseMap) {
                JJNetworkAgent.this.onFailure(responseMap);
            }

        });
    }

    public void cancelRequest(JJBaseRequest request) {
        synchronized (this) {
            for (Iterator<Map.Entry<Integer, JJBaseRequest>> it = requestHashMap.entrySet().iterator(); it.hasNext();){
                Map.Entry<Integer, JJBaseRequest> item = it.next();
                if (item.getValue() == request) {
                    it.remove();
                    break;
                }
            }
        }
    }

    public void cancelAllRequest() {
        lock.lock();

        requestHashMap.clear();

        lock.unlock();
    }

    private Integer addOperation(JJBaseRequest request) {
        Integer index;

        lock.lock();

        requestHashMap.put(requestIndex, request);
        index = requestIndex;
        requestIndex = requestIndex + 1;

        lock.unlock();

        return index;
    }

    private JJBaseRequest removeOperation(Integer index) {
        JJBaseRequest request;

        lock.lock();

        request = requestHashMap.remove(index);

        lock.unlock();

        return request;
    }

    public void onSuccess(Map<String, Object> responseMap) {

        int responseCode = (int) responseMap.get(RESPCODE);
        int requestIndex = (int) responseMap.get(REQINDEX);
        String responseString = (String) responseMap.get(RESPCONTENT);
        Map<String, String> responseHeaders = (Map<String, String>) responseMap.get(RESPHEADERS);

        JJBaseRequest request = removeOperation(requestIndex);
        if (null == request) {
            return;
        }

        request.setResponseCode(responseCode);
        request.setResponseString(responseString);
        request.setResponseHeaders(responseHeaders);
        request.requestCompleteFilter();
        request.getResponseCallBack().onSuccess(request);
    }

    public void onFailure(Map<String, Object> responseMap) {
        int responseCode = (int) responseMap.get(RESPCODE);
        int requestIndex = (int) responseMap.get(REQINDEX);
        String errorString = (String) responseMap.get(RESPERROR);
        Map<String, String> responseHeaders = (Map<String, String>) responseMap.get(RESPHEADERS);

        JJBaseRequest request = removeOperation(requestIndex);
        if (null == request) {
            return;
        }

        JJRequestError error = new JJRequestError();
        error.setCode(responseCode);
        error.setMessage(errorString);

        request.setResponseCode(responseCode);
        request.setError(error);
        request.setResponseHeaders(responseHeaders);
        request.requestFailedFilter();
        request.getResponseCallBack().onFailure(request);
    }
}
